home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-10-05 | 5.9 KB | 218 lines | [TEXT/MPS ] |
- MACHINE MC68020
- MC68881
-
- ;-----------------------------------------------------------
- ; WARNING: These routines require a 68020 or 68030 CPU,
- ; and a 68881 or 68882 floating-point coprocessor!!!
- ;-----------------------------------------------------------
- ; This unit implements a "minimal standard" random number
- ; generator using 32-bit integer arithmetic. This is not
- ; the "best" random number generator possible, but it is
- ; simple, quick, and produces numbers which are "random"
- ; enough for most purposes.
- ;
- ; It is based on the "parametric multiplicative linear con-
- ; gruential algorithm" which was originally proposed by D.
- ; H. Lehmer in 1951. This algorithm generates a sequence
- ; of integers z[1], z[2], z[3]... by repeatedly carrying
- ; out the following calculation:
- ;
- ; z[n+1] = (a * z[n]) mod m
- ;
- ; where "a" and "m" are suitable constants. The successive
- ; "z"s are stored in the variable "seed" in this unit.
- ; They all lie in the range [0..m-1], so dividing them by
- ; "m" gives real numbers which lie in the range [0.0..1.0].
- ;
- ; In 1969, Lewis, Goodman and Miller proposed the choice of
- ; a = 16807 and m = 2**31 - 1 = 2147483647 as particularly
- ; suited for a machine with a 32-bit word length (in their
- ; case, the IBM System/360). The main problem is that the
- ; product a * z[n] can be more than 32 bits long, leading
- ; to integer overflow on many systems (including the Mac).
- ;
- ; In 1979, G. L. Schrage devised an implementation of the
- ; LG&M method which is guaranteed not to produce integer
- ; overflow on any system with a 32-bit word length. It is
- ; this implementation which is used here, in procedure
- ; "UpdateSeed".
- ;
- ; Source: Stephen K. Park and Keith W. Miller, "Random
- ; Number Generators: Good Ones Are Hard to Find", Communi-
- ; cations of the ACM, vol. 31, p. 1192 (October 1988).
- ;
- ; This unit was written in MPW Assembler, v3.2. If the
- ; calling program is written in Pascal, it must use the
- ; interface unit "RandomNumbers.p".
- ;
- ; Jon Bell
- ; Dept. of Physics & Computer Science
- ; Presbyterian College
- ; Clinton SC 29325
- ; CompuServe: #70441,353
- ; October 1991
- ;-----------------------------------------------------------
- ; Numerical constants used in the seed-updating algorithm.
-
- a EQU 16807
- m EQU 2147483647
- q EQU 127773 ; m div a
- r EQU 2836 ; m mod a
-
- ; NOTE: Other possible values for these constants, which
- ; may give "better" results, are:
- ;
- ; a = 48271, q = 44488, r = 3399 or
- ; a = 69621, q = 30845, r = 23902,
- ;
- ; keeping m = 2147483647.
- ;-----------------------------------------------------------
- ; The random number seed (a 32-bit integer) is a global
- ; variable whose value is preserved between calls to
- ; the random number functions.
-
- Seed DS.L 1
-
- ;-----------------------------------------------------------
-
- InitRandomSeed PROC EXPORT
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Initializes the random number seed to a specified value.
- ;
- ; Pascal interface:
- ;
- ; procedure InitRandomSeed (newSeed : longint);
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- newSeed EQU 8
- ParamSize EQU 4
- LocalSize EQU 0
-
- LINK A6, #LocalSize
- MOVE.L newSeed(A6), seed(A5)
- UNLK A6
- RTD #ParamSize
-
- DC.B 'INITRANDOMSEED'
-
- ;-----------------------------------------------------------
-
- RandomSeed FUNC EXPORT
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Returns the current value of the random number seed.
- ;
- ; Pascal interface:
- ;
- ; function RandomSeed : longint;
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- result EQU 8
- LocalSize EQU 0
-
- LINK A6, #LocalSize
- MOVE.L Seed(A5), result(A6)
- UNLK A6
- RTS
-
- DC.B 'RANDOMSEED'
-
- ;-----------------------------------------------------------
-
- UpdateSeed PROC
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Applies the Lehmer / Lewis, Goodman, Miller / Schrage
- ; algorithm to update the random number seed. This
- ; procedure is not to be used outside this unit, therefore
- ; it is not EXPORTed.
- ;
- ; It stores the new seed in the global variable "Seed",
- ; and leaves a copy in register D1 for use by the calling
- ; routine.
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- hi EQU D0
- lo EQU D1
-
- MOVE.L Seed(A5), hi
- TDIVS.L #q, lo:hi
- MULS.L #a, lo
- MULS.L #r, hi
- SUB.L hi, lo
- BGT.S StoreNewSeed
- ADD.L #m, lo ; if lo <= 0
-
- StoreNewSeed
-
- MOVE.L lo, Seed(A5)
- RTS
-
- DC.B 'UPDATESEED'
-
- ;-----------------------------------------------------------
-
- RandomReal FUNC EXPORT
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Updates the random number seed and returns a real number
- ; in the range (0,1).
- ;
- ; Pascal interface:
- ;
- ; function RandomReal : extended;
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- quotient EQU FP0
- newSeed EQU D1
- result EQU 8
- LocalSize EQU 0
-
- LINK A6, #LocalSize
- JSR UpdateSeed
- FMOVE.L newSeed, quotient
- FDIV.L #m, quotient
- FMOVE.X quotient, ([result,A6])
- UNLK A6
- RTS
-
- DC.B 'RANDOMREAL'
-
- ;-----------------------------------------------------------
-
- RandomInteger FUNC EXPORT
-
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- ; Updates the random number seed and returns a longint
- ; in the range [1,max].
- ;
- ; Pascal interface:
- ;
- ; function RandomInteger (max : longint) : longint;
- ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-
- dividend EQU D1
- divisor EQU D0
- result EQU 8
- max EQU 12
- LocalSize EQU 0
- ParamSize EQU 4
-
- LINK A6, #LocalSize
- JSR UpdateSeed
-
- ; The new seed is now in "dividend."
-
- TDIVS.L max(A6), divisor:dividend
-
- ; "Divisor" now contains the remainder.
-
- ADDQ.L #1, divisor
- MOVE.L divisor, result(A6)
- UNLK A6
- RTD #ParamSize
-
- DC.B 'RANDOMINTEGER'
-
- END